package com.dxx.cloud.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dxx.cloud.admin.constant.CommonConst;
import com.dxx.cloud.admin.enums.ErrorEnum;
import com.dxx.cloud.admin.mapper.OrdersMapper;
import com.dxx.cloud.admin.module.entity.GoodsSizeEntity;
import com.dxx.cloud.admin.module.entity.OrderDetailEntity;
import com.dxx.cloud.admin.module.entity.OrdersEntity;
import com.dxx.cloud.admin.module.request.*;
import com.dxx.cloud.admin.module.response.OrderDetailResponse;
import com.dxx.cloud.admin.module.response.OrdersResponse;
import com.dxx.cloud.admin.module.response.UnifiedOrderResponse;
import com.dxx.cloud.admin.module.response.wx.CreateOrderResponse;
import com.dxx.cloud.admin.service.*;
import com.dxx.cloud.admin.service.wx.IDxxWxPayService;
import com.dxx.cloud.admin.utils.BigDecimalUtils;
import com.dxx.cloud.admin.utils.EntityUtils;
import com.dxx.cloud.admin.utils.OrderUtils;
import com.github.binarywang.wxpay.exception.WxPayException;
import jakarta.annotation.Resource;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 销售单表 服务实现类
 * </p>
 *
 * @author dh
 * @since 2025-06-06
 */
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, OrdersEntity> implements IOrdersService {

    @Resource
    private IGoodsService goodsService;

    @Resource
    private IGoodsScanService goodsScanService;

    @Resource
    private IGoodsSizeService goodsSizeService;

    @Resource
    private IOrderDetailService orderDetailService;

    @Resource
    private IDxxWxPayService dxxWxPayService;

    @Override
    public OrdersResponse detailResponseById(Serializable id) {
        if(null == id) {
            return null;
        }
        final OrdersEntity entity = getById(id);
        return entity2Response(entity);
    }

    private OrdersResponse entity2Response(OrdersEntity entity) {
        if (null == entity) {
            return null;
        }
        OrdersResponse ordersResponse = EntityUtils.entity2Response(OrdersResponse.class, entity);
        List<OrderDetailResponse> detailList = new ArrayList<>();
        List<OrderDetailEntity> orderDetailEntities = orderDetailService.listByOrderId(entity.getId());
        Map<Long, BigDecimal> collect = orderDetailEntities.stream().collect(Collectors.toMap(OrderDetailEntity::getGoodsSizeId, OrderDetailEntity::getNumber));

        List<GoodsSizeEntity> goodsSizeEntities = goodsSizeService.listByIds(collect.keySet());
        Map<Long, GoodsSizeEntity> goodsSizeEntityMap = goodsSizeEntities.stream().collect(Collectors.toMap(GoodsSizeEntity::getId, Function.identity()));
        for (OrderDetailEntity orderDetailEntity : orderDetailEntities) {
            GoodsSizeEntity goodsSizeEntity = goodsSizeEntityMap.get(orderDetailEntity.getGoodsSizeId());
            if (null != goodsSizeEntity && null != goodsSizeEntity.getUnitPrice()) {
                OrderDetailResponse orderDetailResponse = new OrderDetailResponse();
                BeanUtils.copyProperties(goodsSizeEntity,orderDetailResponse);
                orderDetailResponse.setNumber(orderDetailEntity.getNumber());
                detailList.add(orderDetailResponse);
            }
        }
        ordersResponse.setOrderDetailList(detailList);
        ordersResponse.setPayAmount(getPayAmount(ordersResponse.getId()));
        return ordersResponse;
    }

    @Override
    public OrdersResponse detailResponseByOutTradeNo(String outTradeNo) {
        if (StringUtils.hasText(outTradeNo)) {
            final OrdersEntity one = getOne(new LambdaQueryWrapper<OrdersEntity>().eq(OrdersEntity::getOutTradeNo, outTradeNo).orderByDesc(OrdersEntity::getId),false);
            return entity2Response(one);
        }
        return null;
    }

    private BigDecimal getPayAmount(Long orderId) {
        BigDecimal payAmount = BigDecimal.ZERO;
        List<OrderDetailEntity> orderDetailEntities = getBaseMapper().listOrderDetailByOrderId(orderId);
        for (OrderDetailEntity orderDetailEntity : orderDetailEntities) {
            payAmount = payAmount.add(orderDetailEntity.getNumber().multiply(orderDetailEntity.getUnitPrice()));
        }
        return payAmount;
    }

    @Override
    public TableDataInfo<OrdersResponse> orderPageList(OrderPageListRequest request) throws Exception {
        Page<OrdersEntity> pageModel = new Page<>( request.getPageNo(), request.getPageSize());
        QueryWrapper<OrdersEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.last("order by ifnull(pay_time,created) desc");
        queryWrapper.eq(null != request.getCustomerId(),"customer_id",request.getCustomerId());
        queryWrapper.eq(null != request.getPayStatus() && request.getPayStatus() > 0,"pay_status",request.getPayStatus());
        queryWrapper.eq(null != request.getReceiveStatus(),"receive_status",request.getReceiveStatus());
        pageModel = page(pageModel,queryWrapper);
        Page<OrdersResponse> ret = new Page<>();
        BeanUtils.copyProperties(pageModel, ret);
        if (null != pageModel.getRecords() && !pageModel.getRecords().isEmpty()) {
            List<OrdersResponse> responseList = new ArrayList<>();
            for (OrdersEntity orderEntity : pageModel.getRecords()) {
                final OrdersResponse ordersResponse = new OrdersResponse();
                BeanUtils.copyProperties(orderEntity,ordersResponse);
                // 查询商品详情
                ordersResponse.setOrderDetailList(orderDetailService.listResponseByOrderId(orderEntity.getId(),ordersResponse.getOrderStatus()));
                // 设置支付方式
                ordersResponse.setPayTypeStr(CommonConst.PayType.getPayTypeDesc(orderEntity.getPayType()));
                ordersResponse.setCompleteStatusStr(CommonConst.OrderPayStatusEnum.getPayStatusDesc(orderEntity.getCompleteStatus()));
                responseList.add(ordersResponse);
            }
            ret.setRecords(responseList);
        }
        return TableDataInfo.build(ret);
    }

    @Override
    public String getLatestOrderSerialNo(OrderLatestRequest request) {
        OrdersEntity entity = getBaseMapper().latestOrderSerialNo(request);
        String result = null;
        if(null != entity){
            String serialNo = entity.getSerialNo();
            result =  new BigDecimal(serialNo).add(BigDecimal.ONE).toString();;
        }else {
            result = OrderUtils.generateOrderNo(request.getMerId(),request.getShopId(),1L);
        }
        return result;
    }

    @Override
    public List<Long> addOrderDetail(OrderAddRequest request) {
        OrderDetailEntity orderDetailEntity = new OrderDetailEntity();
        orderDetailEntity.setOrderId(request.getId());
//        Set<Long> collect = request.getGoodsList().stream().map(OrderAddGoodsModule::getGoodsSizeId).collect(Collectors.toSet());
//        Map<Long, GoodsSizeEntity> sizeIdMap = new HashMap<>();
//        if(!CollectionUtils.isEmpty(collect)) {
//            List<GoodsSizeEntity> goodsSizeEntities = goodsSizeService.listByIds(collect);
//            sizeIdMap = goodsSizeEntities.stream().collect(Collectors.toMap(GoodsSizeEntity::getId, Function.identity()));
//        }

        for (OrderAddGoodsModule addGoodsModule : request.getGoodsList()) {
//            BeanUtils.copyProperties(sizeIdMap.getOrDefault(addGoodsModule.getGoodsSizeId(), new GoodsSizeEntity()),orderDetailEntity);
//            orderDetailEntity.setId(null);
            orderDetailEntity.setNumber(addGoodsModule.getNumber());
            orderDetailEntity.setGoodsSizeId(addGoodsModule.getGoodsSizeId());
            orderDetailService.save(orderDetailEntity);
        }
        return null;
    }


    /**
     * 查询订单中商品列表
     * @param orderId
     * @return
     * @throws Exception
     */
    @Override
    public List<OrderDetailEntity> orderDetailEntities(Long orderId) {
        OrderDetailEntity orderDetailEntity = new OrderDetailEntity();
        orderDetailEntity.setOrderId(orderId);
        return orderDetailService.listByOrderId(orderId);
    }

    private BigDecimal orderDetailPayAccount(BigDecimal payAccount,Integer roundType){
        if(CommonConst.RoundType.ROUND.equals(roundType)){
            payAccount = payAccount.setScale(3, BigDecimal.ROUND_HALF_UP).setScale(0,BigDecimal.ROUND_HALF_UP);
        }
        return payAccount;
    }

    private BigDecimal orderPayAmount(Long orderId,Integer roundType) {
        BigDecimal payAmount = BigDecimal.ZERO;
        for (OrderDetailEntity x : orderDetailEntities(orderId)) {
            BigDecimal goodsPrice = BigDecimalUtils.multipyTwo(x.getUnitPrice(), x.getNetWeight(), x.getNumber());
            goodsPrice = orderDetailPayAccount(goodsPrice,roundType);
            payAmount = BigDecimalUtils.add(payAmount,goodsPrice);
        }
        return payAmount;
    }

    @Override
    public UnifiedOrderResponse payOrder(OrderCompleteRequest request) throws WxPayException {
        UnifiedOrderResponse unifiedOrderResponse = new UnifiedOrderResponse();
        //1.修改订单支付状态
        OrdersEntity entity = getById(request.getId());
        if(null == entity){
            throw new ServiceException(ErrorEnum.ORDER_NOT_EXIST.getMessage());
        }
        entity.setRoundType(request.getRoundType());
        entity.setPayType(request.getPayType());
        entity.setPayStatus(CommonConst.OrderPayStatusEnum.PAYING.getCode());
        BigDecimal fee = orderPayAmount(request.getId(),request.getRoundType());
        entity.setPayAccount(fee);
        updateById(entity);
        //2.开始下单
        if(CommonConst.PayType.PAYED_WITH_CALL_BACK.contains(request.getPayType())){
            PayRequest payRequest = new PayRequest();
            payRequest.setMerId(entity.getMerId());
            payRequest.setPayType(request.getPayType());
            payRequest.setAuthCode(request.getAuthCode());
            payRequest.setFee(fee);
            payRequest.setOpenId(request.getOpenId());
            return dxxWxPayService.unifiedOrder(payRequest);
        }
        return unifiedOrderResponse;
    }

    @Override
    public CreateOrderResponse startPayOrder(OrderCompleteRequest request) throws WxPayException {
        //1.修改订单支付状态
        OrdersEntity entity = getById(request.getId());
        if(null == entity){
            throw new ServiceException(ErrorEnum.ORDER_NOT_EXIST.getMessage());
        }
        entity.setRoundType(request.getRoundType());
        entity.setPayType(request.getPayType());
        entity.setPayStatus(CommonConst.OrderPayStatusEnum.PAYING.getCode());
        BigDecimal fee = getPayAmount(request.getId());
        entity.setPayAccount(fee);
        updateById(entity);
        //2.开始下单
        if(CommonConst.PayType.PAYED_WITH_CALL_BACK.contains(request.getPayType())){
            PayRequest payRequest = new PayRequest();
            payRequest.setMerId(entity.getMerId());
            payRequest.setPayType(request.getPayType());
            payRequest.setAuthCode(request.getAuthCode());
            payRequest.setFee(fee);
            payRequest.setOpenId(request.getOpenId());
            return dxxWxPayService.wxRequestPayment(payRequest);
        }
        return null;
    }
}
